package com.gjy.mongod.codec;

import com.gjy.mongod.domain.DateDomain;
import org.bson.BsonReader;
import org.bson.BsonType;
import org.bson.BsonWriter;
import org.bson.codecs.Codec;
import org.bson.codecs.DecoderContext;
import org.bson.codecs.EncoderContext;
import org.bson.codecs.configuration.CodecProvider;
import org.bson.codecs.configuration.CodecRegistry;

import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;

/**
 * @author 宫静雨
 * @version 1.0
 * @since 2023-09-19 14:31:38
 */
public class DateDomainProvider implements CodecProvider {

    @Override
    public <T> Codec<T> get(Class<T> aClass, CodecRegistry codecRegistry) {
        if (aClass == DateDomain.class) {
            return (Codec<T>) new DateDomainCodec(codecRegistry);
        }
        return null;
    }

    private static class DateDomainCodec implements Codec<DateDomain> {
        private final CodecRegistry codecRegistry;

        public DateDomainCodec(CodecRegistry codecRegistry) {
            this.codecRegistry = codecRegistry;
        }

        @Override
        public DateDomain decode(BsonReader reader, DecoderContext context) {
            DateDomain domain = new DateDomain();
            reader.readStartDocument();
            while (reader.readBsonType() != BsonType.END_OF_DOCUMENT) {
                String s = reader.readName();
                switch (s) {
                    case "_id":
                        reader.readObjectId();
                        break;
                    case "version":
                        domain.setVersion(reader.readInt32());
                        break;
                    case "date":
                        domain.setDate(new Date(new Date(reader.readDateTime()).toInstant().minus(Duration.ofHours(8)).toEpochMilli()));
                        break;
                    case "localDate":
                        domain.setLocalDate(LocalDate.parse(reader.readString()));
                        break;
                    case "localDateTime":
                        domain.setLocalDateTime(LocalDateTime.parse(reader.readString()));
                        break;
                    default:
                        reader.skipValue();
                }
            }
            reader.readEndDocument();
            return domain;
        }

        @Override
        public void encode(BsonWriter writer, DateDomain value, EncoderContext context) {
            writer.writeStartDocument();
            /*if (value.getId() != null) {
                writer.writeObjectId("_id", new ObjectId(Instant.now().getNano(), value.getId()));
            }*/
            writer.writeInt32("version", value.getVersion());
            writer.writeDateTime("date", value.getDate().toInstant().plus(Duration.ofHours(8)).toEpochMilli());
            writer.writeString("localDate", value.getLocalDate().toString());
            writer.writeString("localDateTime", value.getLocalDateTime().toString());
            writer.writeEndDocument();
        }

        @Override
        public Class<DateDomain> getEncoderClass() {
            return DateDomain.class;
        }
    }
}
